<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of BPermitManager
 *
 * @author cnjianfeng@gmail.com
 */
class BPermitManager {

    //put your code here
    protected $app = null;
    public $spaceId = null;

    public function __construct($App = NULL) {
        $this->app = $App;
    }

    public function setApp($App) {
        $this->app = $App;
    }

    protected function getApp($data = NULL) {
        return $this->app == NULL ? Blyn::app()->getActiveApp() : $this->app;
    }

    public function getSpace($data = null) {
        if ($this->spaceId == NULL)
            $this->spaceId = Blyn::app()->getActiveSpace();
        return $this->spaceId;
    }

    public function addPermit($item, $permit, $roles, $spaceId = NULL, $data = NULL) {
        $resourceId = Null;
        $permitId = null;
        $roleId = NULL;

        if (is_numeric($item))
            $resourceId = $item;

        if (is_numeric($permit))
            $permitId = $permit;

        if (is_numeric($roles))
            $roleId = $roles;

        //by default, set access rule as allow
        $access = BPermitObj::Access_Allow;
        if (isset($data['access']) && $data['access'] == BPermitObj::Access_deny)
            $access = BPermitObj::Access_deny;

        if (is_string($permit)) {
            $permitObjects = BPermitObj::findPermitObjects(NULL, NULL, array('permitName' => $permit));
            $permitId = isset($permitObjects[0]) ? $permitObjects[0]->getId() : NULL;
        }

        if (is_string($roles)) {
            $roles = BAuthItem::findAuthItems(NULL, NULL, array('roleName' => $roles));
            $roleId = isset($roles[0]) ? $roles[0]->getId() : NULL;
        }

        if ($resourceId > 0 && $permitId > 0 && $roleId > 0) {

            return $this->addPermitsToStore($resourceId, $permitId, $roleId, $spaceId, $this->getspaceId(), $access);
        }

        if ($resourceId > 0 && $permitId > 0 && is_array($roles)) {
            foreach ($roles as $role) {
                $roleId = NULL;
                if (is_numeric($role)) {
                    $roleId = $role;
                }
                if (is_string($role)) {
                    $roles = BAuthItem::findAuthItems(NULL, NULL, array('roleName' => $roles));
                    $roleId = isset($roles[0]) ? $roles[0]->getId() : NULL;
                }
                return $this->addPermitsToStore($resourceId, $permitId, $roleId, $spaceId, $this->getspaceId(), $access);
            }
        }
        return FALSE;
    }

    protected function addPermitsToStore($resourceId, $permitId, $roleId, $spaceId, $appId, $access) {

        $mResourcePermission = BMResourcePermission::model()->findByAttributes(
                array(
                    'resource_id' => $resourceId,
                    'permit_id' => $permitId,
                    'authitem_id' => $roleId,
                    'app_id' => $appId,
                    'space_id' => $spaceId,
                    'access' => $access
                ));
        //if not find record, insert new record
        if ($mResourcePermission == NULL) {
            $mResourcePermission = new BMResourcePermission();
            $mResourcePermission->permit_id = $permitId;
            $mResourcePermission->resource_id = $resourceId;
            $mResourcePermission->authitem_id = $roleId;
            /**
             * in most of case, add permission only for specific Space, however, some application may
             * add permission for all Space in application
             */
            $mResourcePermission->space_id = $spaceId;
            $mResourcePermission->app_id = $this->getApp()->getId();
            $mResourcePermission->access = $access;
            return $mResourcePermission->save();
        }
        return FALSE;
    }

    public function removePermit($resourceId, $permit, $roles = null, $spaceId = NULL, $data = NULL) {

        if (!$resourceId > 0 || $permit == NULL)
            return FALSE;

        if (is_numeric($permit))
            $permitId = $permit;

        if (is_string($permit)) {
            $permitObjects = BPermitObj::findPermitObjects(NULL, NULL, array('permitName' => $permit));
            if (count($permitObjects) > 0)
                return FALSE;
            $permitId = isset($permitObjects[0]) ? $permitObjects[0]->getId() : NULL;
        }
        /**
         * delete all permits for $resourceItem
         */
        if ($permit == BPermitObj::Scope_All) {
            $mPermits = $this->getPermits($resourceId);

            foreach ($mPermits as $resourcePermitId => $item) {
                BMResourcePermission::model()->deleteByPk($resourcePermitId);
            }
            return;
        }

        if ($roles == BAuthItem::Scope_All) {
            $mPermits = $this->getPermits($resourceId, $permitId);
            foreach ($mPermits as $resourcePermitId => $item) {
                BMResourcePermission::model()->deleteByPk($resourcePermitId);
            }
            return;
        }

        if (is_array($roles)) {
            foreach ($roles as $role) {
                if (is_string($role)) {
                    $aRoles = BAuthItem::findAuthItems();
                    $roleId = isset($aRoles[0]) ? $aRoles[0]->getId() : NULL;
                }
                if (is_numeric($role))
                    $roleId = $role;

                if ($roleId != NULL && $roleId > 0) {
                    $mPermits = $this->getPermits($resourceId, $permitId, $roleId);
                    foreach ($mPermits as $resourcePermitId => $item) {
                        BMResourcePermission::model()->deleteByPk($resourcePermitId);
                    }
                    return;
                }
            }
        }
    }

    /**
     * this function use to find permits
     * @return array return is a array of like {$item, $permitObjects,$roles}
     * @param type $item
     * @param type $permit
     * @param type $roles
     * @param type $data 
     */
    public function getPermits($resourceId, $access = NULL, $permit = null, $roleId = null, $spaceId = NULL, $data = NULL) {

        if ($spaceId == NULL)
            $spaceId = $this->getspaceId();

        if ($access == NULL)
            $access = BPermitObj::Access_Allow;

        $resourcePermissions = array();

        $permitId = NULL;
        if (is_numeric($permit))
            $permitId = $permit;
        if (is_string($permit)) {
            $permitObjects = BPermitObj::findPermitObjects(NULL, NULL, array('permitName' => $permit));
            if (count($permitObjects) == 1)
                $permitId = isset($permitObjects[0]) ? $permitObjects[0]->getId() : NULL;
        }

        /**
         * return all permissions for resourceItem
         */
        if ($permitId == NULL) {
            $sql = "select * from bln_application_resource_permit_authitem where (space_id=" . BSpace::All_Spaces . " or space_id = " . $spaceId
                    . ") and resource_id=" . $resourceId . " and app_id=" . $this->getApp()->getId() . ";";
        }
        if ($permitId > 0)
            $sql = "select * from bln_application_resource_permit_authitem where (space_id=" . BSpace::All_Spaces . " or space_id = " . $spaceId
                    . ") and resource_id=" . $resourceId . " and app_id=" . $this->getApp()->getId() . " and permit_id=" . $permitId;

        if ($roleId != null && $roleId > 0)
            $sql = $sql . " and authitem_id = " . $roleId;

        $mResourcePermits = BMResourcePermission::model()->findAllBySql($sql);

        foreach ($mResourcePermits as $mResourcePermit) {
            $permitObj = new BPermitObj($mResourcePermit->permit_id);
            $role = new BAuthItem($mResourcePermit->authitem_id);
            $resourceObj = new BResource($mResourcePermit->resource_id);
            $resourcePermissions[$mResourcePermit->_id] = array('resource' => $resourceObj, 'permit' => $permitObj, 'role' => $role, 'access' => $mResourcePermit->access);
        }

        return $resourcePermissions;
    }

    /**
     * this function will check user's permit on some item,access type can be allow or deny base on access parameter
     * @param type $item
     * @param type $user
     * @param type $data
     */
    public function checkPermits($resourceId = null, $permit = NULL, $userId = NULL, $access = NULL, $data = NULL) {

        if (is_numeric($permit))
            $permitId = $permit;

        $permitId = NULL;
        if (is_numeric($permit))
            $permitId = $permit;
        if (is_string($permit)) {
            $permitObj = BPermitObj::findPermitObjectByName($permit);
            if ($permitObj != NULL)
                $permitId = $permitObj->getId();
        }

        if ($resourceId == NULL || $permitId == NULL)
            return FALSE;

        if ($access == NULL)
            $access = BPermitObj::Access_Allow;
        if ($userId == NULL)
            $userId = Blyn::app()->getCurrentUser()->getId();

        /**
         * get permit roles on item
         */
        $permitRoles = $this->getPermits($resourceId, $access, $permitId);

        $authManager = Blyn::app()->getActiveApp()->getAuthManager();

        $userRoles = $authManager->getUserRoles($userId);

        foreach ($permitRoles as $pRole) {
            $role = $pRole['role'];
            foreach ($userRoles as $uRole) {
                if ($role->getId() == $uRole->getId())
                    return TRUE;
            }
        }

        return FALSE;
    }

}

?>
